package com.azh.server.datam.indexs;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.azh.server.datam.pagecache.PageCache;

/**
 * @author zhaozhenhang <zhaozhenhang@kuaishou.com>
 * Created on 2022-04-26
 * 页面索引，后续考虑b+树索引方式
 * 缓存了每一页的空闲空间，在进行插入时可以快速从磁盘或者缓存中检查每个页面的信息
 *
 * pageInfo: 页号 和 空闲空间大小
 */
public class PageIndex {

    // 将一页划分40个区间
    private static final int intervals_no = 40;

    private static final int threshold = PageCache.PAGE_SIZE / intervals_no;

    private Lock lock;
    private List<PageInfo>[] lists;

    public PageIndex() {
        lock = new ReentrantLock();
        lists = new List[intervals_no + 1];
        for (int i = 0; i < intervals_no + 1; i++) {
            lists[i] = new ArrayList<>();
        }
    }

    /**
     * 查找页面 todo 同一个页不允许并发写，如何后续可以尝试实现提高并发量
     * @param spaceSize
     * @return
     */
    public PageInfo select(int spaceSize) {
        lock.lock();
        try {
            int number = spaceSize / threshold;
            // todo 找到空闲页面，防止死循环得加个判断
            if (number < intervals_no) {
                number++;
            }
            while (number <= intervals_no) {
                if (lists[number].size() == 0) {
                    number++;
                    continue;
                }
                return lists[number].remove(0);
            }
            return null;
        }finally {
            lock.unlock();
        }

    }

    public void add(int pageNumber, int freeSpace) {
        lock.lock();
        try {
            int number = freeSpace / threshold;
            lists[number].add(new PageInfo(pageNumber, freeSpace));
        }finally {
            lock.unlock();
        }
    }
}
